package com.flyan.game.motafx;

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.app.scene.GameView;
import com.almasb.fxgl.core.util.LazyValue;
import com.almasb.fxgl.dsl.components.EffectComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.physics.CollisionHandler;
import com.flyan.game.motafx.component.BattleComponent;
import com.flyan.game.motafx.component.character.BraveComponent;
import com.flyan.game.motafx.component.item.ItemComponent;
import com.flyan.game.motafx.component.terrain.TerrainComponent;
import com.flyan.game.motafx.core.console.GameConsole;
import com.flyan.game.motafx.core.enums.DirEnum;
import com.flyan.game.motafx.core.enums.EntityClassifyEnum;
import com.flyan.game.motafx.core.enums.EntityTypeEnum;
import com.flyan.game.motafx.core.enums.ZLayerEnum;
import com.flyan.game.motafx.core.event.EventService;
import com.flyan.game.motafx.core.map.FloorMap;
import com.flyan.game.motafx.core.map.TowerMap;
import com.flyan.game.motafx.core.orb.BraveOrb;
import com.flyan.game.motafx.core.panel.GameInfoPanel;
import com.flyan.game.motafx.core.util.bgm.BgmUtils;
import com.flyan.game.motafx.core.util.console.ConsoleUtils;
import com.flyan.game.motafx.core.util.position.PositionUtils;
import com.flyan.game.motafx.effect.npc.TransactionEffect;
import com.flyan.game.motafx.entity.MotaEntityFactory;
import com.flyan.game.motafx.entity.animate.AnimateEntityFactory;
import com.flyan.game.motafx.entity.terrain.TerrainEntityFactory;
import com.flyan.game.motafx.ui.ConsolePane;
import com.flyan.game.motafx.ui.LeftInfoPane;
import com.flyan.game.motafx.ui.RightInfoPane;
import com.flyan.game.motafx.ui.TransactionPage;
import javafx.geometry.Point2D;
import javafx.scene.input.KeyCode;

import java.util.List;
import java.util.Map;

import static com.almasb.fxgl.dsl.FXGL.*;
import static com.flyan.game.motafx.config.GameConfig.*;

/**
 * 魔塔主程序
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/1/31
 */
public class MotaApp extends GameApplication {

    /**
     * 事件服务
     */
    public EventService eventService = new EventService();

    /**
     * 左侧信息栏
     */
    public LeftInfoPane leftInfoPane = new LeftInfoPane();

    /**
     * 右测信息栏
     */
    public RightInfoPane rightInfoPane;

    /**
     * 游戏信息面板
     */
    public GameInfoPanel gameInfoPanel = new GameInfoPanel();

    /**
     * 游戏控制台
     */
    public GameConsole console = new GameConsole();

    /**
     * 魔塔地图
     */
    public TowerMap towerMap;

    /**
     * 全局交易页面
     */
    public TransactionPage transactionPage;

    /**
     * 勇者灵球
     */
    public BraveOrb braveOrb;

    public LazyValue<Entity> braveEntityLv = new LazyValue<>(() -> getGameWorld().getEntitiesByType(EntityTypeEnum.CHARACTER_BRAVE).get(0));

    @Override
    protected void onPreInit() {
        /* 初始音量 */
        getSettings().setGlobalMusicVolume(0.5);
        getSettings().setGlobalSoundVolume(0.7);
        /* 播放背景音乐 */
        BgmUtils.play("B_067XGW.mp3"); // 不死军团（一区）
//        BgmUtils.play("A_032XGW.mp3"); // 公主
    }

    @Override
    protected void initSettings(GameSettings settings) {
        settings.setTitle("魔塔FX");
        settings.setVersion("0.11");
        settings.setWidth(BACKGROUND_WIDTH);
        settings.setHeight(BACKGROUND_HEIGHT + CONSOLE_HEIGHT);
    }

    @Override
    protected void initGameVars(Map<String, Object> vars) {
        /* 游戏选项 */
        vars.put("game:sleep", false);
        /* 交易页面选中选项id，默认选中第一项 */
        vars.put("TransactionPage.selectedItemId", 0);
        vars.put("TransactionPage.itemSize", 0);
    }

    @Override
    protected void initGame() {
        /* 背景 */
        getGameScene().setBackgroundRepeat("images/statusBackground.jpg");

        /* 设置实体工厂 */
        getGameWorld().addEntityFactory(new MotaEntityFactory());
        getGameWorld().addEntityFactory(new AnimateEntityFactory());
        getGameWorld().addEntityFactory(new TerrainEntityFactory());

        /* 左侧信息栏 */
        GameView leftInfoPaneView = new GameView(leftInfoPane, ZLayerEnum.HIGH.getIndex());
        getGameScene().addGameView(leftInfoPaneView);

        /* 右侧信息栏 */
        rightInfoPane = new RightInfoPane();
        GameView rightInfoPaneView = new GameView(rightInfoPane, ZLayerEnum.HIGH.getIndex());
        getGameScene().addGameView(rightInfoPaneView);

        /* 控制台 */
        ConsolePane consolePane = new ConsolePane();
        GameView consoleView = new GameView(consolePane, ZLayerEnum.HIGH.getIndex());
        getGameScene().addGameView(consoleView);
        console.setShowText(consolePane.getText());

        /* 全局交易页面 */
        transactionPage = new TransactionPage();

        /* 为地图外围上一圈空气墙 */
        Point2D leftTopMapPoint = PositionUtils.getMapPosition(1, 1);
        for (double x = leftTopMapPoint.getX();
             x <= leftTopMapPoint.getX() + (11 * GRID_SIZE);
             x += GRID_SIZE) {
            spawn(EntityTypeEnum.TERRAIN_AIR_WALL.name(), x, leftTopMapPoint.getY() - (GRID_SIZE + 1));
        }
        Point2D rightTopMapPoint = PositionUtils.getMapPosition(1, 11);
        for (double y = rightTopMapPoint.getY();
             y <= rightTopMapPoint.getY() + (11 * GRID_SIZE);
             y += GRID_SIZE) {
            spawn(EntityTypeEnum.TERRAIN_AIR_WALL.name(), rightTopMapPoint.getX() + (GRID_SIZE + 1), y);
        }
        Point2D rightBottomMapPoint = PositionUtils.getMapPosition(11, 11);
        for (double x = rightBottomMapPoint.getX();
             x >= rightBottomMapPoint.getX() - (11 * GRID_SIZE);
             x -= GRID_SIZE) {
            spawn(EntityTypeEnum.TERRAIN_AIR_WALL.name(), x, rightBottomMapPoint.getY() + (GRID_SIZE + 1));
        }
        Point2D leftBottomMapPoint = PositionUtils.getMapPosition(11, 1);
        for (double y = leftBottomMapPoint.getY();
             y >= leftBottomMapPoint.getY() - (11 * GRID_SIZE);
             y -= GRID_SIZE) {
            spawn(EntityTypeEnum.TERRAIN_AIR_WALL.name(), leftBottomMapPoint.getX() - (GRID_SIZE + 1), y);
        }

        /* 创建地图 */
        towerMap = new TowerMap();
        int floorNumber = 5;
        for (int i = 0; i <= floorNumber; i++) {
            towerMap.addFloor(new FloorMap("map/50/%df.json".formatted(i)));
        }
        towerMap.setCurrentFloorNumber(1);
        towerMap.drawMap();

        /* 初始化勇者灵球 */
        braveOrb = new BraveOrb(towerMap, braveEntityLv.get().getComponent(BraveComponent.class));

        ConsoleUtils.println("游戏加载完成");
    }

    @Override
    protected void initInput() {
        onKeyBuilder(KeyCode.UP)
                .onActionBegin(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (effectComponent.hasEffect(TransactionEffect.class)){
                        int selectedItemId = geti("TransactionPage.selectedItemId");
                        set("TransactionPage.selectedItemId", Math.max(0, selectedItemId - 1));
                    }
                })
                .onAction(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (!effectComponent.hasEffect(TransactionEffect.class)) {
                        entity.getComponent(BraveComponent.class).move(DirEnum.UP);
                    }
                });
        onKeyBuilder(KeyCode.DOWN)
                .onActionBegin(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (effectComponent.hasEffect(TransactionEffect.class)) {
                        int selectedItemId = geti("TransactionPage.selectedItemId");
                        int itemSize = geti("TransactionPage.itemSize");
                        set("TransactionPage.selectedItemId", Math.min(itemSize, selectedItemId + 1));
                    }
                })
                .onAction(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (!effectComponent.hasEffect(TransactionEffect.class)) {
                        entity.getComponent(BraveComponent.class).move(DirEnum.DOWN);
                    }
                });
        onKeyBuilder(KeyCode.LEFT)
                .onAction(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (!effectComponent.hasEffect(TransactionEffect.class)) {
                        entity.getComponent(BraveComponent.class).move(DirEnum.LEFT);
                    }
                })
                .onActionEnd(() -> braveEntityLv.get().getComponent(BraveComponent.class).stopMove());
        onKeyBuilder(KeyCode.RIGHT)
                .onAction(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (!effectComponent.hasEffect(TransactionEffect.class)) {
                        entity.getComponent(BraveComponent.class).move(DirEnum.RIGHT);
                    }
                });
        onKeyBuilder(KeyCode.ENTER)
                .onActionBegin(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    Entity entity = braveEntityLv.get();
                    EffectComponent effectComponent = entity.getComponent(EffectComponent.class);
                    if (effectComponent.hasEffect(TransactionEffect.class)) {
                        /* 确认交易选项 */
                        int selectedItemId = geti("TransactionPage.selectedItemId");
                        transactionPage.enterItem(selectedItemId);
                    }
                });

        /* 打印当前楼层怪物伤害 */
        onKeyBuilder(KeyCode.H)
                .onActionBegin(() -> {
                    if (getb("game:sleep")) { // 游戏休眠中
                        return;
                    }

                    List<BraveOrb.Prediction> predictions = braveOrb.currentFloorPredication();
                    braveOrb.printPrediction(predictions);
                });
    }

    @Override
    protected void initPhysics() {
        /* 添加人物和所有的物品碰撞 */
        for (EntityTypeEnum characterEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.CHARACTER)) {
            for (EntityTypeEnum itemEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.ITEM)) {
                getPhysicsWorld().addCollisionHandler(new CollisionHandler(characterEntityType, itemEntityType) {
                    @Override
                    protected void onCollisionBegin(Entity character, Entity item) {
                        item.getComponent(ItemComponent.class).onCollisionBegin(character);
                    }
                });
            }
        }
        /* 添加人物和所有地形的碰撞 */
        for (EntityTypeEnum characterEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.CHARACTER)) {
            for (EntityTypeEnum terrainEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.TERRAIN)) {
                getPhysicsWorld().addCollisionHandler(new CollisionHandler(characterEntityType, terrainEntityType) {
                    @Override
                    protected void onCollisionBegin(Entity character, Entity terrain) {
                        terrain.getComponent(TerrainComponent.class).onCollisionBegin(character);
                    }
                });
            }
        }
        /* 添加人物和所有怪物的碰撞 */
        for (EntityTypeEnum characterEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.CHARACTER)) {
            for (EntityTypeEnum monsterEntityType : EntityTypeEnum.getByClassify(EntityClassifyEnum.MONSTER)) {
                getPhysicsWorld().addCollisionHandler(new CollisionHandler(characterEntityType, monsterEntityType) {
                    @Override
                    protected void onCollisionBegin(Entity character, Entity monster) {
                        monster.getComponent(BattleComponent.class).defend(character);
                    }
                });
            }
        }
    }

    /**
     * 程序入口
     */
    public static void main(String[] args) {
        launch(args);
    }

}
